/*-------------------------------------------------------- 
* Module Name : OLApplication
* Version : 1.0
* 
* Software Name : Qt App Template
* Version : 1.0
*
* Copyright � 2010 � 2011 France T�l�com
* This software is distributed under the LGPL v2.1 license,
* the text of which is available at http://www.gnu.org/licenses/lgpl-2.1.html
* or see the "LICENSE.txt" file for more details.
*
*--------------------------------------------------------
* File Name   : OLApplication.h
*
* Created     : 07 June 2011
* Author(s)   : Omer Saleem
*
* Description :
* Main header file for Qt App Template. The App Template is
* a Qt C++ based framework to quickly build rich mobile 
* applications.
*
*--------------------------------------------------------
* 1.0 - First open source release
*
*/

#ifndef __OLAPPLICATION_H__
#define __OLAPPLICATION_H__

#include <QtGui/QApplication>
#include <QtGui/QWidget>
#include <QtCore/QAbstractAnimation>
#include <QtCore/QMap>

class OLButton;
class OLToolbar;
class OLStatusbar;
class OLMenuPane;
class OLView;
class OLMainWindow;
class OLMenuSurface;

typedef QList<OLButton*> OLButtonList;
typedef QList<QWidget*> OLWidgetList;

#define OLApp (qobject_cast<OLApplication*>(qApp))

/*
 The OLApplication class is a custom application framework to quickly bring
 up applications that follow the Orange Labs style guidelines. This application
 framework is used to provide application services and centralise the theming
 and interaction of applications.

 Some of the services provided is menu handling, dialogs view switching and
 many more.

 To use the application template framework, simple use this class instead of
 QApplication and the application will start when the exec() call is made.
 */
class OLApplication : public QApplication
{
    Q_OBJECT

public:
    /*
     Defines the orientation options. 'portrait' and 'landscape' will force the
     application into a particular orientation and 'systemdefault' will use
     the platform's configuration.
     */
    enum OrientationOptions {
        systemdefault = 0,
        portrait,
        landscape
    };

public:

    OLApplication(int& argc, char *argv[]);
    ~OLApplication();

    /*
     Returns the window title/application title. To set the title use the SLOT.
     */
    QString windowTitle() const;

    // Use setWindowTitle() slot to set the application title

    // Splash screen handling
    /*
     This changes the splash screen image. The image is stretched to fit the screen.
     Once this method is called, the splashscreen can only be dismissed with a call
     to dismissSplashScreen(). This can be called many times and the images will
     transition from the old to the new image.
     */
    void changeSplashScreenImage(const QString& pixmap);

    /*
     This allows the caller to set a layout with its own widgets. This can be called
     many times. Once this method is called, the splashscreen can only be dismissed
     with a call to dismissSplashScreen().
     */
    void changeSplashScreenLayout(QLayout* layout);

    // Use dismissSplashScreen() slot to remove splashscreen

    // Toolbar methods
    /*
     Gets the list of toolbar buttons currently set in the toolbar
     */
    OLButtonList toolbarButtons() const;

    /*
     Adds a toolbar button. The 'button' parameter should contain the button that
     is already formatted with child widgets for its design. The caller should connect
     to the button's clicked() signal for notification when it has been pressed.

     The hideForMini parameter should contain a list of QWidget derived elements in this
     button that should be hidden when the toolbar is made mini or when in landscape view.
     */
    void addToolbarButton(OLButton* button, const OLWidgetList& hideForMini);

    // several more toolbar methods exist as slots.

    // View handling methods
    /*
     Returns the current size of the view.
     */
    QSize viewSize() const;

    /*
     Returns the current orientation.
     */
    OrientationOptions orientation() const;

    /*
     Set the base view. If this is called when one or more stacked view exist, the stacked views
     are removed or deleted.

     The 'view' parameter should be the QWidget-derived class that forms the basis of the view.
     This can also be a graphics view, web view or qml view.
     The 'options' parameter is the orientation options that the view should follow.
     The 'keep' parameter incidated whether the view should be deleted or not when removed.
     A true value will not delete the view and simply emit the viewRemoved(QWidget*) signal.
     */
    void setView(QWidget* view, OrientationOptions options = systemdefault, bool keep=false);

    /*
     Adds a stacked view to the view stack. When using stacked views, the application's 'x' icon
     changes to a back button.

     The 'view' parameter should be the QWidget-derived class that forms the basis of the view.
     This can also be a graphics view, web view or qml view.
     The 'options' parameter is the orientation options that the view should follow.
     The 'keep' parameter incidated whether the view should be deleted or not when removed.
     A true value will not delete the view and simply emit the viewRemoved(QWidget*) signal.
     */
    void addStackedView(QWidget* view, OrientationOptions options = systemdefault, bool keep=false);

    /*
     Returns the current view.
     */
    QWidget* currentView() const;

    /*
     Returns the parent widget of views to allow views to be created with its parent at c'tor.
     This is a convenience function so that views can be created without owning their own windows.
     */
    QWidget* viewParent() const;

    // Menu handling
    /*
     Adds a menu item. The method returns a randomly generated id that can be used with the
     menuItemClicked(int) signal to determine when the menu has been selected. The method also
     allows the caller to provide a slot/signal that can be connected to when the item is selected
     using the optional 'receiver' and 'method' parameters.
     */
    int addMenuItem(const QString& menuitem, const QObject* receiver=0, const char* method=0);

    /*
     Same as the above method but instead allows the caller to provider its own id to use with the
     menuItemClicked(int) signal. Allows the caller to defines its own enum for menu items.
     */
    void addMenuItem(int id, const QString& menuitem, const QObject* receiver=0, const char* method=0);

    /*
     Completely removes a menu item from the menu pane. The 'id' parameter is used to identify the menu item.
     */
    void removeMenuItem(int id);

    /*
     Hide a menu item from the menu pane. The order of the menu is maintained. The 'id' parameter is used
     to identify the menu item.
     */
    void hideMenuItem(int id);

    /*
     Shows a menu item. Use this if it was previously hidden.
     */
    void showMenuItem(int id);

    // Dialog handling
    /*
     Shows a dialog with a text string. The buttons provided will all automatically dismiss the dialog.
     If no buttons are provided, a default one is automatically created. An id is returned that can be
     used to dismiss the dialog manually.

     The parameters are:
     'icon' - an icon to represent the dialog. If no icon is required, pass am an empty QPixmap()
     'title' - the string for the dialog title
     'message' - a string for the dialog message
     'buttons' -  a list of the buttons to display
     */
    int showDialog(const QPixmap& icon, const QString& title, const QString& message, const OLButtonList& buttons);

    /*
     Shows a dialog with a layout. The layout can be used to create a custom dilaog with any UI widgets.
     The buttons provided will all automatically dismiss the dialog. If no buttons are provided, a
     default one is automatically created. An id is returned that can be used to dismiss the dialog
     manually.

     The parameters are:
     'icon' - an icon to represent the dialog. If no icon is required, pass am an empty QPixmap()
     'title' - the string for the dialog title
     'body' - a layout class defining the layout of the widgets
     'buttons' -  a list of the buttons to display
     */
    int showDialog(const QPixmap& icon, const QString& title, QLayout* body, const OLButtonList& buttons);

    /*
     Manually dismiss the dialog identified by its id. Can be used when external actions can cause the
     dialog to be dismissed.
     */
    void dismissDialog(int id);

public slots:
    /*
     Sets the application title. Can be set at any time and any number of times.
     */
    void setWindowTitle(const QString& title);

    /*
     The the splashscreen has been changed from the default using images or layouts, the splashscreen
     must be dismissed using this slot method. Callers can also use this to pre-load data while the
     splashscreen is showing.
     */
    void dismissSplashScreen();

    /*
     Shows a text banner with the message in the 'message' parameter. The 'autodismiss' flags indicates
     whether the banner disappears automatically after a fixed time period or whether the user must
     click to dismiss.
     */
    void showBanner(const QString& message, bool autodismiss);

    /*
     Slot method for showing the menu.
     */
    void showMenu();

    /*
     Slot method for hiding the menu.
     */
    void hideMenu();

    /*
     Slot method for handling home button clicks
     */
    void homeButtonClicked();

    /*
     Slot method for showing the info panel.
     */
    void showInfoPanel();

    /*
     Slot method for hiding the info panel.
     */
    void hideInfoPanel();

    /*
     Slot method for hiding the toolbar.
     */
    void hideToolbar();

    /*
     Slot method for showing the toolbar (if it had been previously hidden).
     */
    void showToolbar();

    /*
     Slot method for changing the toolbar to mini-mode.
     */
    void miniToolbar();

    /*
     Slot method for changing the toolbar to normal (large) mode.
     */
    void fullToolbar();

    /*
     Slot method for changing the toolbar position to the top of the application.
     */
    void topToolbarPosition();

    /*
     Slot method for changing the toolbar position to the (default) bottom of the application.
     */
    void bottomToolbarPosition();
    
    // Waiting spinner
    /*
     Shows a waiting spinner that covers the whole application. Use hideSpinner() to remove it.
     caption specifies an optional string to be displayed below the spinner
     */
    void showSpinner(const QString& caption = "");

    /*
     Shows a waiting spinner that covers just the view. Use hideSpinner() to remove it.
     caption specifies an optional string to be displayed below the spinner
     */
    void showViewSpinner(const QString& caption = "");

    /*
     Removes the spinner (if one exists).
     */
    void hideSpinner();

private slots: // private slots, do not use
    void handleSwitchToLandscape();
    void handleSwitchToPortrait();
    void appResized();
    void removeStackedView();

signals:
    /*
     The application has started and in focus after the splashscreen has gone. Set the first
     base view using setView() at this point.
     */
    void appStarted();

    /*
     A menu item with the id has been selected by the user.
     */
    void menuItemClicked(int id);

    /*
     The view size has changed. The new size is provided.
     */
    void viewSizeChanged(const QSize& size);

    /*
     The provided view has just been added.
     */
    void viewAdded(QWidget* view);

    /*
     The provided view has just been removed from the stack. This is called when the view
     was added with the 'keep' flag set to true.
     */
    void viewRemoved(QWidget* view);

    /*
     The provided view is coming into focus. Can be used to know when to 'wake-up' the view.
     */
    void viewFocusIn(QWidget* view);

    /*
     The provided view is losing focus. Can be used to know to put a view to 'sleep'.
     */
    void viewFocusOut(QWidget* view);

    /*
     The application has switched orientation to portrait.
     */
    void switchToPortrait();

    /*
     The application has switched orientation to landscape.
     */
    void switchToLandscape();

    /*
      A dialog has been closed. The closed dialog can be identified by it id.
      */
    void dialogClosed(int id);

signals:
    // private signals, do not use
    void titleChanged(const QString& title);
    void baseViewActivated();
    
private:
    OLMenuSurface* getOrCreateMenuSurface();

private:
    OLMainWindow* m_mainwidget;
    OLView* m_appWindow;
    OLToolbar* m_toolbar;
    OLStatusbar* m_statusbar;
    QObject* m_obj;
    OLWidgetList m_hideForLandscape;
    bool m_miniToolbar;
    bool m_toolbarBottomPos;
};

#endif // __OLAPPLICATION_H__
